﻿using System;
using System.Collections.Generic;
using System.Linq;
using FellowshipOne.API;
using FellowshipOne.API.Base;
using FellowshipOne.API.Base.Interfaces;
using FellowshipOne.API.Events.Model;
using FellowshipOne.API.Events.Sets;
using FellowshipOne.API.People.Model;
using FellowshipOne.API.People.Sets;
using FellowshipOne.API.Realms;
using MasVida.WebApi.Controllers;
using MasVida.WebApi.Models.DataObject;
using MasVida.WebApi.Models.Requests;
using MasVida.WebApi.Models.Responses;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using Newtonsoft.Json.Linq;
using Shouldly;
using Attendance = FellowshipOne.API.Events.Model.Attendance;
using AttendanceCollection = FellowshipOne.API.Events.Model.AttendanceCollection;

namespace MasVida.WebApi.Tests.Controllers
{
    [TestClass]
    public class AttendanceControllerTests
    {
        [TestMethod]
        public void GetAttendancesByAttendanceSummaryId()
        {
            const string attendanceSummaryId = "54";
            Mock<IApiSet<AttendanceCollection>> attendanceCollectionMock = new Mock<IApiSet<AttendanceCollection>>();
            int? personId = 2;
            attendanceCollectionMock.Setup(ac => ac.Get(It.Is<string>(s => s == attendanceSummaryId)))
                .Returns(new AttendanceCollection(new List<Attendance>()
                {
                    new Attendance() { Person = new PersonEdit() { ID = personId } }
                }));
            Mock<IPeople> personMock = new Mock<IPeople>();
            personMock.Setup(p => p.Get(It.IsAny<string>())).Returns(new Person() {ID = personId, FirstName = "Ruben", LastName = "Cardenas"});
            IRestClient client = GetRestClient(attendanceCollectionMock, person: personMock);
            AttendanceController controller = new AttendanceController(client);

            AttendanceRequest attendanceRequest = new AttendanceRequest()
            {
                AccessTicket = new F1OAuthTicket(),
                AttendanceSummaryId = attendanceSummaryId
            };

            AttendanceResponse response = controller.GetAttendancesByAttendanceSummaryId(JObject.FromObject(attendanceRequest));

            attendanceCollectionMock.Verify(a => a.Get(It.IsAny<string>()), "Get was not performed");
            response.ShouldNotBe(null);
            response.Success.ShouldBe(true, "Method should be successfull");
            List<AttendanceDO> list = response.Attendances.ToList();
            list.Count.ShouldBe(1, "There should be 1 attendace Summary retrieved");
            list[0].Person.Name.ShouldBe("Ruben Cardenas");
        }

        [TestMethod]
        public void UpdateAttendances()
        {
            const string attendanceId = "123", attendanceSummaryId = "123123";
            Mock<IAttendance> attendanceMock = new Mock<IAttendance>();
            attendanceMock.Setup(
                ac => ac.Update(It.Is<Attendance>(acc => acc.IsPresent), attendanceId, attendanceSummaryId));
            Mock<IApiSet<AttendanceCollection>> attendanceCollectionMock = new Mock<IApiSet<AttendanceCollection>>();
            attendanceCollectionMock.Setup(ac => ac.Get(It.Is<string>(s => s == attendanceSummaryId)))
                .Returns(new AttendanceCollection(new List<Attendance>()
                {
                    new Attendance() {IsPresent = false, ID = int.Parse(attendanceId)}
                }));
            IRestClient client = GetRestClient(attendanceCollectionMock, attendanceMock);
            AttendanceController controller = new AttendanceController(client);

            AttendanceRequest attendanceRequest = new AttendanceRequest()
            {
                Attendances = new List<AttendanceDO>()
                {
                    new AttendanceDO() {AttendanceId = int.Parse(attendanceId), IsPresent = true}
                },
                AttendanceSummaryId = attendanceSummaryId
            };

            AttendanceResponse response = controller.UpdateAttendances(JObject.FromObject(attendanceRequest));

            attendanceMock.Verify(ac => ac.Update(It.Is<Attendance>(acc => acc.IsPresent), attendanceId, attendanceSummaryId));
            response.ShouldNotBe(null);
            response.Success.ShouldBe(true);
        }

        private IRestClient GetRestClient(Mock<IApiSet<AttendanceCollection>> attendanceCollectionMock, Mock<IAttendance> attendance = null, Mock<IPeople> person = null)
        {
            Mock<IEventsRealm> eventsMock = new Mock<IEventsRealm>();
            eventsMock.Setup(e => e.AttendanceCollection).Returns(attendanceCollectionMock.Object);
            if (attendance != null)
                eventsMock.Setup(e => e.Attendance).Returns(attendance.Object);
            IRestClient restClient = Mock.Of<IRestClient>();
            restClient.EventsRealm = eventsMock.Object;
            if (person != null)
            {
                Mock<IPersonRealm> personsMock = new Mock<IPersonRealm>();
                personsMock.Setup(p => p.People).Returns(person.Object);
                restClient.PeopleRealm = personsMock.Object;
            }
            return restClient;
        }
    }
}
